package com.yb.auth.core.bean;

import com.alibaba.fastjson2.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.yb.auth.core.constant.LoginConstant;
import com.yb.core.constant.DateTimeConstant;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.*;

/**
 * Copyright (C), 2022-2022, 姚兵
 * Author: 32210
 * Date: 2022/11/12 22:22
 * FileName: SysUser
 * Description:
 */

@Data
@TableName("t_sys_user")
public class SysUser implements UserDetails {

    @TableId(type = IdType.AUTO)
    private Integer id;

    private Integer userId;

    private String username;

    private String password;

    private String mobile;

    @TableField(exist = false)
    private LoginConstant.LoginType loginType;
    @TableField(exist=false)
    private List<String> permissions;

    @JSONField(serialize = false)//不参与序列化
    @TableField(exist=false)
    private  List<GrantedAuthority> authorities;


    //以下字段用int 0代表启用 1禁用
    private  Integer accountNonExpired=0;

    private  Integer accountNonLocked=0;

    private  Integer credentialsNonExpired=0;

    private  Integer enabled=0;

    @DateTimeFormat(pattern = DateTimeConstant.DATETIME_PATTERN)
    @JsonFormat(pattern =  DateTimeConstant.DATETIME_PATTERN)
    private LocalDateTime createTime;

    @DateTimeFormat(pattern = DateTimeConstant.DATETIME_PATTERN)
    @JsonFormat(pattern =  DateTimeConstant.DATETIME_PATTERN)
    private LocalDateTime updateTime;

    public SysUser(){

    }

    public SysUser(SysUser sysUser,List<String> permissions){
        this.id=sysUser.getId();
        this.userId=sysUser.getUserId();
        this.username=sysUser.username;
        this.password=sysUser.password;
        this.mobile=sysUser.mobile;
        this.permissions=permissions;
        this.createTime=sysUser.createTime;
        this.updateTime=sysUser.updateTime;
        this.authorities=  AuthorityUtils.createAuthorityList(permissions.toArray(new String[0]));
        this.enabled=sysUser.enabled;
        this.accountNonExpired=sysUser.accountNonExpired;
        this.accountNonLocked=sysUser.accountNonLocked;
        this.credentialsNonExpired=sysUser.credentialsNonExpired;
    }
    public SysUser(String username, String password){
        super();
        this.username=username;
        this.password=password;
    }

    public SysUser(String username, String password, List<String> permissions){
            Assert.isTrue(username != null && !"".equals(username) && password != null&&permissions != null,
                    "Cannot pass null or empty values to constructor");
            this.username=username;
            this.password=password;
            this.permissions=permissions;
            this.authorities=  AuthorityUtils.createAuthorityList(permissions.toArray(new String[0]));
    }


    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    @Override
    public boolean isAccountNonExpired() {
        return this.accountNonExpired==0;
    }

    @Override
    public boolean isAccountNonLocked() {
        return this.accountNonLocked==0;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return this.credentialsNonExpired==0;
    }

    @Override
    public boolean isEnabled() {
        return this.enabled==0;
    }


    public void setPermissions(List<String> permissions) {
        this.permissions=permissions;
        this.authorities=  AuthorityUtils.createAuthorityList(permissions.toArray(new String[0]));
    }

    private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
        Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
        // Ensure array iteration order is predictable (as per
        // UserDetails.getAuthorities() contract and SEC-717)
        SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(new AuthorityComparator());
        for (GrantedAuthority grantedAuthority : authorities) {
            Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
            sortedAuthorities.add(grantedAuthority);
        }
        return sortedAuthorities;
    }

    private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {


        @Override
        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
            // Neither should ever be null as each entry is checked before adding it to
            // the set. If the authority is null, it is a custom authority and should
            // precede others.
            if (g2.getAuthority() == null) {
                return -1;
            }
            if (g1.getAuthority() == null) {
                return 1;
            }
            return g1.getAuthority().compareTo(g2.getAuthority());
        }

    }


    public String getLoginType() {
        return Objects.isNull(loginType)?"":loginType.name();
    }


    public LoginConstant.LoginType loginType(){
        return this.loginType;
    }
}
